package huanzhao.erp.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import huanzhao.erp.domain.entity.ExternalAccount;
import huanzhao.erp.domain.entity.Position;
import huanzhao.erp.domain.entity.Staff;
import huanzhao.erp.domain.entity.Team;
import huanzhao.erp.domain.enumerate.error.PermissionError;
import huanzhao.erp.domain.enumerate.error.ProcessError;
import huanzhao.erp.domain.enumerate.error.ValidationError;
import huanzhao.erp.domain.po.Result;
import huanzhao.erp.domain.types.DepartmentType;
import huanzhao.erp.domain.types.PermissionType;
import huanzhao.erp.domain.vo.ExternalAccountVO;
import huanzhao.erp.domain.vo.PositionVO;
import huanzhao.erp.domain.vo.StaffVO;
import huanzhao.erp.domain.vo.TeamVO;
import huanzhao.erp.service.*;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Objects;


/**
 * @author April
 * 2024/6/9 下午3:41
 * @version 1.0
 */
@RestController
@RequestMapping("/api/staff")
@Validated
public class StaffController {
    final BasicService basicService;
    final StaffService staffService;
    private final PositionService positionService;
    private final TeamService teamService;
    private final PermissionService permissionService;

    public StaffController(BasicService basicService, StaffService staffService, PositionService positionService, TeamService teamService, PermissionService permissionService) {
        this.basicService = basicService;
        this.staffService = staffService;
        this.positionService = positionService;
        this.teamService = teamService;
        this.permissionService = permissionService;
    }


    /**
     * 查询所有员工的id和姓名
     *
     * @return List<Staff>
     * 2024/6/29 下午8:43:05
     */
    @GetMapping("/all")
    public Result<List<StaffVO>> getAllStaffIdAndName() {
        return Result.ok(staffService.getAllStaffIdAndName());
    }

    /**
     * 改变员工的休假、离职状态
     *
     * @param type 0->休假状态，1->离职状态
     * @return Result<?>
     * 2024/10/2 13:14:38
     */
    @PutMapping("state")
    public Result<?> changeStaffState(@RequestParam long staffId, @RequestParam @Range(max = 1, message = "状态类型错误") int type) {
        if (staffId != basicService.getCurrentStaffId()) {
            // 鉴权
            if (type == 0) {
                permissionService.checkPermissionToStaff(staffId, PermissionType.VOCATION);
            } else {
                permissionService.checkPermissionToStaff(staffId, PermissionType.REMOVE);
            }
        } else {
            // 修改自己状态的情况
            if (type == 1) {
                return Result.error("不可修改自己的离职情况");
            }
        }
        return staffService.changeStaffState(staffId, type);
    }

    /**
     * 按条件获取员工信息
     *
     * @param teamId     员工所在团队id，为空则代表全部员工
     * @param name       员工名（模糊查询）
     * @param department 员工部门
     * @param pageNum    当前页码
     * @param pageSize   每页记录数量
     * @return IPage<Staff>
     * 2024/6/11 下午8:59:35
     */
    @GetMapping("")
    public Result<IPage<StaffVO>> getStaffByCondition(@RequestParam(required = false) Long teamId,
                                                      @RequestParam(required = false) String name,
                                                      @RequestParam(required = false) @Range(max = 3,message = "部门代码错误") Integer department,
                                                      @RequestParam int pageNum,
                                                      @RequestParam int pageSize) {
        return Result.ok(staffService.getStaffByCondition(teamId, name, department, pageNum, pageSize));
    }


    /**
     * 修改员工基本信息
     *
     * @return Result<?>
     * 2024/6/11 下午9:01:37
     */
    @PutMapping("")
    public Result<?> updateStaff(@RequestParam long staffId, @RequestParam(required = false) String name, @RequestParam(required = false) String phone) {
        if (staffId != basicService.getCurrentStaffId()) {
            // 鉴权
            permissionService.checkPermissionToStaff(staffId, PermissionType.EDIT);
        }
        Result<?> validation = staffService.checkStaffInfo(name, phone, null);
        if (validation.isError()) {
            return validation;
        }
        if (StringUtils.isNotBlank(name)) {
            // 修改员工手机号
            Result<?> result = staffService.updateStaffName(staffId, name);
            if (result.isError()) {
                return result;
            }
        }
        if (StringUtils.isNotBlank(phone)) {
            // 修改员工手机号
            Staff existStaff = staffService.getById(staffId);
            // 检查员工手机号是否已存在
            if (!existStaff.getPhone().equals(phone) && staffService.getStaffByPhone(phone) != null) {
                return Result.error(ValidationError.VALIDATION_ERROR, "手机号已存在");
            }
            Result<?> result = staffService.updateStaffPhone(staffId, phone);
            if (result.isError()) {
                return result;
            }
        }
        return Result.ok("修改成功");
    }


    /**
     * 修改员工密码
     *
     * @param oldPass 旧密码
     * @param newPass 新密码
     * @return Result<?>
     * 2024/6/11 下午8:57:41
     */
    @PutMapping("/change/password")
    public Result<?> changePassword(@RequestParam long staffId, @RequestParam(required = false) String oldPass, @RequestParam @NotBlank @Length(min = 64, max = 64) String newPass) {
        if (staffId == basicService.getCurrentStaffId()) {
            // 修改自己密码的情况
            if (StringUtils.isBlank(oldPass)) {
                return Result.error(ValidationError.PASSWORD_VALIDATION_FAILED, "原密码不可为空");
            }
            if (!basicService.getCurrentStaff().getPassword().equals(oldPass)) {
                return Result.error(ValidationError.PASSWORD_VALIDATION_FAILED, "原密码错误");
            }
        } else {
            // 鉴权
            permissionService.checkPermissionToStaff(staffId, PermissionType.EDIT);
        }
        return staffService.changePass(staffId, newPass);
    }


    /**
     * 添加员工
     *
     * @return Result<?>
     * 2024/6/11 下午9:02:20
     */
    @PostMapping("")
    @SaCheckPermission("company:staff:add")
    public Result<?> addStaff(@RequestParam @NotBlank String name, @RequestParam @NotBlank String phone, @RequestParam @NotBlank String password) {
        Result<?> validation = staffService.checkStaffInfo(name, phone, password);
        if (validation.isError()) {
            return validation;
        }
        return Result.ok();
    }

    /**
     * 获取员工所在的所有团队
     *
     * @param staffId 员工id
     * @return List<Position>
     * 2024/6/17 下午8:41:31
     */
    @GetMapping("/position")
    public Result<List<PositionVO>> getStaffTeams(@RequestParam long staffId) {
        return Result.ok(positionService.getStaffPositions(staffId));
    }

    /**
     * 将员工添加到团队
     *
     * @param position 员工职位信息
     * @return Result<?>
     * 2024/6/17 下午8:42:36
     */
    @PostMapping("/position")
    public Result<?> addStaffToTeam(@RequestBody Position position) {
        StpUtil.checkPermissionOr("team:" + position.getTeamId() + ":staff:add", "dept:qc:staff:add");

        Result<?> validation = positionService.checkPositionInfo(position);
        if (validation.isError()) {
            return validation;
        }
        // 检查员工是否已在团队中
        if (staffService.checkStaffInTeam(position.getStaffId(), position.getTeamId())) {
            return Result.error(ValidationError.VALIDATION_ERROR, "员工已在团队中");
        }
        return positionService.addStaffToTeam(position);
    }

    /**
     * 修改员工在某团队的职位
     *
     * @param position 员工职位信息
     * @return Result<?>
     * 2024/6/17 下午8:42:36
     */
    @PutMapping("/position")
    public Result<?> updatePosition(@RequestBody Position position) {
        StpUtil.checkPermissionOr("team:" + position.getTeamId() + ":staff:position", "dept:qc:staff:position");
        Result<?> validation = positionService.checkPositionInfo(position);
        if (validation.isError()) {
            return validation;
        }
        // 检查员工是否已在团队中
        if (!staffService.checkStaffInTeam(position.getStaffId(), position.getTeamId())) {
            return Result.error(PermissionError.STAFF_NOT_IN_TEAM, "员工未在团队中");
        }
        return positionService.updatePosition(position);
    }

    /**
     * 将员工从团队中移除
     *
     * @param staffId 员工id
     * @param teamId  团队id
     * @return Result<?>
     * 2024/6/17 下午8:44:17
     */
    @DeleteMapping("/position")
    public Result<?> removeStaffFromTeam(@RequestParam long staffId, @RequestParam long teamId) {
        StpUtil.checkPermissionOr("team:" + teamId + ":staff:remove", "dept:qc:staff:remove");
        if (!staffService.checkStaffInTeam(staffId, teamId)) {
            return Result.error(PermissionError.STAFF_NOT_IN_TEAM);
        }
        return positionService.removeStaffFromTeam(staffId, teamId);
    }

    /**
     * 将员工添加到部门
     *
     * @param staffId 员工id
     * @param dept    部门类型
     * @return Result<?>
     * 2024/10/2 09:54:21
     */
    @PostMapping("dept")
    public Result<?> addStaffToDept(@RequestParam long staffId, @RequestParam @Range(max = 2, message = "部门代码错误") int dept) {
        DepartmentType departmentType = DepartmentType.of(dept);
        StpUtil.checkPermission("dept:" + departmentType + ":staff:add");
        return staffService.updateStaffDept(staffId, departmentType, true);
    }

    @DeleteMapping("dept")
    public Result<?> removeStaffToDept(@RequestParam long staffId, @RequestParam int dept) {
        DepartmentType departmentType = DepartmentType.of(dept);
        StpUtil.checkPermission("dept:" + departmentType + ":staff:remove");
        return staffService.updateStaffDept(staffId, departmentType, false);
    }

    /**
     * 查询所有团队信息
     *
     * @return List<Team>
     * 2024/6/11 下午9:05:46
     */
    @GetMapping("team")
    @SaCheckPermission("company:team:view")
    public Result<List<TeamVO>> getAllTeams() {
        return Result.ok(teamService.getAllTeams());
    }

    /**
     * 添加团队
     *
     * @param team 团队信息
     * @return Result<?>
     * 2024/6/11 下午9:05:57
     */
    @PostMapping("team")
    @SaCheckPermission("company:team:add")
    public Result<?> addTeam(@RequestBody Team team) {
        Result<?> validation = teamService.checkTeamInfo(team);
        if (validation.isError()) {
            return validation;
        }
        if (teamService.getTeamByName(team.getName()) != null) {
            return Result.error(ValidationError.VALIDATION_ERROR, "团队名已存在");
        }
        return teamService.addTeam(team);
    }

    /**
     * 修改团队信息
     *
     * @param team 团队信息
     * @return Result<?>
     * 2024/6/11 下午9:06:03
     */
    @PutMapping("team")
    @SaCheckPermission("company:team:edit")
    public Result<?> updateTeam(@RequestBody @NotNull Team team) {
        if (team.getId() == null) {
            return Result.error(ValidationError.VALIDATION_ERROR, "团队id不可为空");
        }
        Result<?> validation = teamService.checkTeamInfo(team);
        if (validation.isError()) {
            return validation;
        }
        Team existTeam = teamService.getById(team.getId());
        if (existTeam == null) {
            return Result.error(ProcessError.TEAM_NOT_FOUND, "团队不存在");
        }
        if (!existTeam.getName().equals(team.getName()) && teamService.getTeamByName(team.getName()) != null) {
            return Result.error(ValidationError.VALIDATION_ERROR, "团队名已存在");
        }
        return teamService.updateTeam(team);
    }

    /**
     * 解散团队
     *
     * @param id 团队id
     * @return Result<?>
     * 2024/6/11 下午9:06:10
     */
    @DeleteMapping("/team/{id}")
    @SaCheckPermission("company:team:remove")
    public Result<?> disbandTeam(@PathVariable Long id) {
        if (id == null) {
            return Result.error(ValidationError.VALIDATION_ERROR, "团队id不可为空");
        }
        return teamService.disbandTeam(id);
    }

    /**
     * 查询员工的外部账号
     *
     * @return Result<List < ExternalAccountVO>>
     * 2024/10/2 13:15:52
     */
    @GetMapping("external/account")
    public Result<List<ExternalAccountVO>> getStaffExternalAccount(@RequestParam long staffId) {
        if (staffId != basicService.getCurrentStaffId()) {
            // 查看的不是自己的外部账号，需要鉴权
            StpUtil.checkPermission("company:staff:eaccount:view");
        }
        return Result.ok(staffService.getStaffExternalAccount(staffId));
    }

    /**
     * 添加员工外部账号
     *
     * @return Result<?>
     * 2024/10/2 13:16:02
     */
    @PostMapping("external/account")
    public Result<?> addExternalAccount(@RequestBody @NotNull ExternalAccount externalAccount) {
        if (!Objects.equals(externalAccount.getStaffId(), basicService.getCurrentStaffId())) {
            // 不为自己添加外部账号，需要鉴权
            StpUtil.checkPermission("company:staff:eaccount:add");
        }
        Result<?> validation = staffService.checkExternalAccount(externalAccount, false);
        if (validation.isError()) {
            return validation;
        }
        return staffService.addExternalAccount(externalAccount);
    }

    /**
     * 修改员工外部账号
     *
     * @return Result<?>
     * 2024/10/2 13:16:07
     */
    @PutMapping("external/account")
    public Result<?> updateExternalAccount(@RequestBody ExternalAccount externalAccount) {
        if (!Objects.equals(externalAccount.getStaffId(), basicService.getCurrentStaffId())) {
            // 修改的不是自己的外部账号，需要鉴权
            StpUtil.checkPermission("company:staff:eaccount:edit");
        }
        Result<?> validation = staffService.checkExternalAccount(externalAccount, true);
        if (validation.isError()) {
            return validation;
        }
        return staffService.updateExternalAccount(externalAccount);
    }

    /**
     * 删除员工外部账号
     *
     * @return Result<?>
     * 2024/10/2 13:16:11
     */
    @DeleteMapping("external/account")
    public Result<?> removeExternalAccount(@RequestParam long eAccountId) {
        return staffService.removeExternalAccount(eAccountId);
    }

    /**
     * 获取员工外部账号密码
     * @return Result<String>
     * 2024/10/5 09:17:51
     */
    @GetMapping("/external/account/password")
    public Result<String> getExternalAccountPassword(@RequestParam long eAccountId){
        return staffService.getExternalAccountPassword(eAccountId);
    }

    /**
     * 修改员工权限
     *
     * @param staffId    员工id
     * @param permissions 权限列表
     * @return Result<?>
     * 2024/10/2 13:16:22
     */
    @PutMapping("permission")
    public Result<?> updatePermission(@RequestParam long staffId, @RequestParam @NotNull List<String> permissions) {
        Long currentStaffId = basicService.getCurrentStaffId();
        if (!Objects.equals(currentStaffId, basicService.getGlobalSetting().getManagerId())) {
            return Result.error("无权修改权限");
        }
        if (staffId == currentStaffId) {
            return Result.error("已为业务经理，具有最高权限");
        }
        return staffService.updatePermission(staffId, permissions);
    }
}
